from BaseViewTestCase import BaseViewTestCase
from skillchallenge.game import *
from skillchallenge.models import *
from django.db.models import Q

class MockRandom:
    def __init__(self):
        self.results = []
    
    def randint(self, min, max):
#        print 'OWH YEAH BABY!'
        return self.results.pop(0)

class SkillChallengeTestCase(BaseViewTestCase):
    
    def setUp(self):
        self.game = Game()
        self.quest = Quest()
        self.char = Character.objects.create(name=Name.objects.create(text='name 1'), npc=False)
        self.char.train(Skill.objects.create(name='skill 1'))
        self.random = MockRandom()
        self.game.set_random(self.random) 
          
    def test_skill_test_event(self):
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been tiggered.')],
                                                         info = 'player test')
        
        skill_test = self.quest.skill_test(player_event, Skill.objects.get(id=1), 15)
        
        self.assertTrue(player_event.description.endswith('(test : ' + Skill.objects.get(id=1).name + ' / ' + str(15) + ')'))
        
        self.random.results.append(20)
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        self.assertTrue(SkillTest.objects.get(id=1).completer == self.char)  
    
    def test_skill_test_success(self):
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        player_event2 = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event II',
                                                         actions = [self.quest.code_engine.create_message_action('player event II have been triggered.')],
                                                         info = 'player test II')
        
        skill_test = self.quest.skill_test(player_event, Skill.objects.get(id=1), 15)
        
        static_event = self.quest.event_engine.add_event(preconditions = [self.quest.code_engine.create_always_fail_precon()],
                                actions = [self.quest.code_engine.create_message_action('this event have been triggered.')],
                                online=True)
        self.quest.chain_if_success(player_event, player_event2, skill_test)
        self.quest.trigger_if_success(player_event, static_event, skill_test)
        
        self.random.results.append(20)
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        response = self.client.get('/game/' + str(self.char.id))
        
        self.assertTrue('player event have been triggered.' in response.content)
        self.assertTrue('(test succeeded)' in response.content)
        self.assertTrue('this event have been triggered.' in response.content)
        self.assertTrue(len(self.__event_options__(player_event2, response.context[0].dicts[0]['options'])) > 0)
        
    def test_skill_test_failure(self):
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        player_event2 = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event II',
                                                         actions = [self.quest.code_engine.create_message_action('player event II have been triggered.')],
                                                         info = 'player test II')
        
        skill_test = self.quest.skill_test(player_event, Skill.objects.get(id=1), 15)
        
        static_event = self.quest.event_engine.add_event(preconditions = [self.quest.code_engine.create_always_fail_precon()],
                                actions = [self.quest.code_engine.create_message_action('this event have been triggered.')],
                                online=True)
        self.quest.chain_if_fail(player_event, player_event2, skill_test)
        self.quest.trigger_if_fail(player_event, static_event, skill_test)
        
        self.random.results.append(1)
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        response = self.client.get('/game/' + str(self.char.id))
        
        self.assertTrue('player event have been triggered.' in response.content)
        self.assertTrue('(test failed)' in response.content)
        self.assertTrue('this event have been triggered.' in response.content)
        self.assertTrue(len(self.__event_options__(player_event2, response.context[0].dicts[0]['options'])) > 0)
        
    def test_skill_challenge_success(self):
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        player_event2 = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event II',
                                                         actions = [self.quest.code_engine.create_message_action('player event II have been triggered.')],
                                                         info = 'player test II')
        
        skill_test = self.quest.skill_test(player_event, Skill.objects.get(id=1), 15)
        
        skill_challenge = self.quest.skill_challenge('skill challenge 1', 1, 1)
        skill_challenge.skilltest_set.add(skill_test)
                
        static_event = self.quest.event_engine.add_event(preconditions = [self.quest.code_engine.create_always_fail_precon()],
                                actions = [self.quest.code_engine.create_message_action('this event have been triggered.')],
                                online=True)
        
        self.quest.chain_if_challenge_success(player_event, player_event2, skill_challenge)
        self.quest.trigger_if_challenge_success(player_event, static_event, skill_challenge)
        
        self.random.results.append(20)
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        response = self.client.get('/game/' + str(self.char.id))
        
        self.assertTrue('(test challenge: ' + str(skill_challenge.name) + ' succeeded)' in response.content)
        self.assertTrue('this event have been triggered.' in response.content)
        self.assertTrue(len(self.__event_options__(player_event2, response.context[0].dicts[0]['options'])) > 0)
        
    def test_skill_challenge_failure(self):
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        player_event2 = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event II',
                                                         actions = [self.quest.code_engine.create_message_action('player event II have been triggered.')],
                                                         info = 'player test II')
        
        skill_test = self.quest.skill_test(player_event, Skill.objects.get(id=1), 15)
        
        skill_challenge = self.quest.skill_challenge('skill challenge 1', 1, 1)
        skill_challenge.skilltest_set.add(skill_test)
                
        static_event = self.quest.event_engine.add_event(preconditions = [self.quest.code_engine.create_always_fail_precon()],
                                actions = [self.quest.code_engine.create_message_action('this event have been triggered.')],
                                online=True)
        
        self.quest.chain_if_challenge_fail(player_event, player_event2, skill_challenge)
        self.quest.trigger_if_challenge_fail(player_event, static_event, skill_challenge)
        
        self.random.results.append(1)
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        response = self.client.get('/game/' + str(self.char.id))
        
        self.assertTrue('(test challenge: ' + str(skill_challenge.name) + ' failed)' in response.content)
        self.assertTrue('this event have been triggered.' in response.content)
        self.assertTrue(len(self.__event_options__(player_event2, response.context[0].dicts[0]['options'])) > 0)
        
    def test_quest_accept(self):
        quest = self.quest.new_quest("quest test", 150)
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        self.quest.turn_quest_acceptance(quest, player_event)
        
        response = self.client.get('/game/' + str(self.char.id))
        
        self.assertTrue(('test player event (to accept quest ' + str(quest.name) + ')') in response.content)
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        response = self.client.get('/game/' + str(self.char.id))
        
        self.assertTrue(('Quest: ' + str(quest.name) + ' reward -> ' + str(quest.reward)) in response.content)
    
    def test_quest_end_success(self):
        quest = self.quest.new_quest("quest test", 100)
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        self.quest.turn_quest_acceptance(quest, player_event)
        
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        
        quest = QuestModel.objects.get(id=1)
        
        event_2 = self.quest.event_engine.add_event(online=True, description='quest end event',
                                                         actions = [self.quest.code_engine.create_message_action('the quest is ended.')],
                                                         info = 'quest end test')
    
        event_3 = self.quest.event_engine.add_event(online=True, description='quest post-end event',
                                                         actions = [self.quest.code_engine.create_message_action('the quest is post-ended.')],
                                                         info = 'quest post-end test')
        
        self.quest.successful_end(quest, event_2)
        self.quest.quest_event(quest, event_3, True)
        self.game.fire(event_2)
        response = self.client.get('/game/' + str(self.char.id))
        self.assertTrue('the quest is post-ended.' in response.content)
        self.assertTrue(('Quest: ' + str(quest.name) + ' reward -> ' + str(quest.reward)) not in response.content)
        self.assertTrue(('Completed Quests: ' + str(quest.name)) in response.content)
        self.assertTrue(Character.objects.get(id=1).score == quest.reward)
    
    def test_quest_end_failure(self):
        quest = self.quest.new_quest("quest test", 100)
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        self.quest.turn_quest_acceptance(quest, player_event)
        
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        
        quest = QuestModel.objects.get(id=1)
        
        event_2 = self.quest.event_engine.add_event(online=True, description='quest end event',
                                                         actions = [self.quest.code_engine.create_message_action('the quest is ended.')],
                                                         info = 'quest end test')
        
        event_3 = self.quest.event_engine.add_event(online=True, description='quest post-end event',
                                                         actions = [self.quest.code_engine.create_message_action('the quest is post-ended.')],
                                                         info = 'quest post-end test')
        
        self.quest.failure_end(quest, event_2)
        self.quest.quest_event(quest, event_3, False)
        self.game.fire(event_2)
        response = self.client.get('/game/' + str(self.char.id))
        self.assertTrue('the quest is post-ended.' in response.content)
        self.assertTrue(('Quest: ' + str(quest.name)) not in response.content)
        self.assertTrue(('Failed Quests: ' + str(quest.name)) in response.content)
        self.assertTrue(Character.objects.get(id=1).score == 0)
        
    def test_quest_event(self):
        quest = self.quest.new_quest("quest test", 0)
        player_event = self.quest.event_engine.add_event(player_will=True, online=True, description='test player event',
                                                         actions = [self.quest.code_engine.create_message_action('player event have been triggered.')],
                                                         info = 'player test')
        self.quest.turn_quest_acceptance(quest, player_event)
        player_event2 = self.quest.event_engine.add_event(player_will=True, online=True, description='on quest test player event',
                                                         actions = [self.quest.code_engine.create_message_action('on quest player event have been triggered.')],
                                                         info = 'on quest player test')
        
        
        self.quest.quest_event(quest, player_event2)
        
        response = self.client.get('/game/' + str(self.char.id))
        self.assertTrue(len(self.__event_options__(player_event2, response.context[0].dicts[0]['options'])) == 0)
        
        self.game.player_fire(self.game.player_available()[0], self.char)
        response = self.client.get('/game/' + str(self.char.id))
        self.assertTrue(len(self.__event_options__(player_event2, response.context[0].dicts[0]['options'])) > 0)

        
    
    